﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TeacherLeftHand.DataAccess;
using TeacherLeftHand.Messages;
using TeacherLeftHand.Model;
using TeacherLeftHand.Util;

namespace TeacherLeftHand.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class CreateNewKIViewModel : ViewModelBase, IDataErrorInfo
    {
        /// <summary>
        /// Initializes a new instance of the CreateNewKIViewModel class.
        /// </summary>
        public CreateNewKIViewModel()
        {
            // initialize object
            _ki = new KnowledgeItem();
            _kiAccessor = new KnowledgeItemAccessor();
            SubjectList = new ObservableCollection<string>(_kiAccessor.GetSubjectList());
            TopicList = new ObservableCollection<string>(_kiAccessor.GetTopicList());

            // commands
            SaveCommand = new RelayCommand(() =>
                                               {
                                                   var msg = new UpdateKIMessage { Action = _action, KnowledgeItem = _ki };
                                                   if (_action.Equals(UpdateAction.Add))
                                                   {
                                                       _ki.ID = Add();
                                                       if (_ki.ID > 0)
                                                       {
                                                           Messenger.Default.Send(msg);
                                                       }
                                                   }
                                                   else if (Save())
                                                   {
                                                       Messenger.Default.Send(msg);
                                                   }
                                                   Messenger.Default.Send(new CloseWindowMessage());
                                               });

            CancelCommand = new RelayCommand(() => Messenger.Default.Send(new NewWindowMessage
                                                                              {
                                                                                  Action = WindowAction.Close,
                                                                                  ItemType = _ki
                                                                              }));
            // register message
            Messenger.Default.Register<CreateNewKIWindowMessage>(this, msg =>
                                                                           {
                                                                               _ki = new KnowledgeItem();
                                                                               switch (msg.Action)
                                                                               {
                                                                                   case WindowAction.OpenCreate:
                                                                                       _action = UpdateAction.Add;
                                                                                       
                                                                                       Title =
                                                                                           DataHelper.CreateNewKITitle;
                                                                                       Messenger.Default.Send(new NewWindowMessage
                                                                                       {
                                                                                           Action = WindowAction.OpenCreate,
                                                                                           ItemType = _ki
                                                                                       });
                                                                                       break;
                                                                                   case WindowAction.OpenUpdate:
                                                                                       _action = UpdateAction.Update;
                                                                                       Title =
                                                                                           DataHelper.UpdateKITitle;
                                                                                       
                                                                                       ClassLevel = msg.Item.ClassLevel;
                                                                                       Subject = msg.Item.Subject;
                                                                                       Topic = msg.Item.Topic;
                                                                                       TopicNo = msg.Item.TopicNo;
                                                                                       KIType = msg.Item.KIType;
                                                                                       Content = msg.Item.Content;
                                                                                       _ki.ID = msg.Item.ID;

                                                                                       Messenger.Default.Send(new NewWindowMessage
                                                                                       {
                                                                                           Action = WindowAction.OpenUpdate,
                                                                                           ItemType = _ki
                                                                                       });
                                                                                       
                                                                                       break;
                                                                               }

                                                                           });
        }


        #region properties

        private UpdateAction _action = UpdateAction.Add;
        private const string SubjectListPropertyName = "SubjectList";
        private ObservableCollection<string> _subjectList = new ObservableCollection<string>();

        /// <summary>
        /// The <see cref="CanSave" /> property's name.
        /// </summary>
        public const string CanSavePropertyName = "CanSave";

        private bool _canSave;

        /// <summary>
        /// Gets the CanSave property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool CanSave
        {
            get
            {
                return string.IsNullOrEmpty(Error);
            }

            set
            {
                if (_canSave == value)
                {
                    return;
                }

                _canSave = value;
                // Update bindings, no broadcast
                RaisePropertyChanged(CanSavePropertyName);
            }
        }
        /// <summary>
        /// The <see cref="Title" /> property's name.
        /// </summary>
        public const string TitlePropertyName = "Title";

        private string _title = DataHelper.CreateNewKITitle;

        /// <summary>
        /// Gets the Title property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string Title
        {
            get
            {
                return _title;
            }

            set
            {
                if (_title == value)
                {
                    return;
                }
                _title = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(TitlePropertyName);
            }
        }

        public ObservableCollection<string> SubjectList
        {
            get { return _subjectList; }
            set
            {
                if (_subjectList == value)
                {
                    return;
                }

                _subjectList = value;
                RaisePropertyChanged(SubjectListPropertyName);
            }
        }

        public ObservableCollection<int> ClassLevelList
        {
            get { return DataHelper.ClassLevelList; }
        }

        public ObservableCollection<string> KITypeList
        {
            get { return DataHelper.KITypeList; }
        }


        public const string ClassLevelPropertyName = "ClassLevel";
        public int ClassLevel
        {
            get { return _ki.ClassLevel; }
            set
            {
                if (_ki.ClassLevel != value)
                {
                    _ki.ClassLevel = value;
                    RaisePropertyChanged(ClassLevelPropertyName);
                    SubjectList = new ObservableCollection<string>(_kiAccessor.GetSubjectByClass(value));
                }
            }
        }

        public const string SubjectPropertyName = "Subject";
        public string Subject
        {
            get { return _ki.Subject; }
            set
            {
                if (_ki.Subject != value)
                {
                    _ki.Subject = value;
                    RaisePropertyChanged(SubjectPropertyName);
                    TopicList = new ObservableCollection<string>(_kiAccessor.GetTopicByClassAndSubject(ClassLevel, Subject));
                }
            }
        }


        public const string ContentPropertyName = "Content";
        public string Content
        {
            get { return _ki.Content; }
            set
            {
                if (_ki.Content != value)
                {
                    _ki.Content = value;
                    RaisePropertyChanged(ContentPropertyName);
                }
            }
        }


        public const string KITypePropertyName = "KIType";
        public string KIType
        {
            get { return _ki.KIType; }
            set
            {
                if (_ki.KIType != value)
                {
                    _ki.KIType = value;
                    RaisePropertyChanged(KITypePropertyName);
                }
            }
        }

        public const string TopicPropertyName = "Topic";
        public string Topic
        {
            get { return _ki.Topic; }
            set
            {
                if (_ki.Topic != value)
                {
                    _ki.Topic = value;
                    RaisePropertyChanged(TopicPropertyName);
                }
            }
        }

        public const string TopicNoPropertyName = "TopicNo";
        public int TopicNo
        {
            get { return _ki.TopicNo; }
            set
            {
                if (_ki.TopicNo != value)
                {
                    _ki.TopicNo = value;
                    RaisePropertyChanged(TopicNoPropertyName);
                }
            }
        }

        /// <summary>
        /// The <see cref="TopicList" /> property's name.
        /// </summary>
        public const string TopicListPropertyName = "TopicList";

        private ObservableCollection<string> _topicList = new ObservableCollection<string>();

        /// <summary>
        /// Gets the TopicList property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<string> TopicList
        {
            get
            {
                return _topicList;
            }

            set
            {
                if (_topicList == value)
                {
                    return;
                }

                _topicList = value;
                // Update bindings, no broadcast
                RaisePropertyChanged(TopicListPropertyName);
            }
        }

        public ICommand SaveCommand
        {
            get;
            private set;
        }

        public ICommand CancelCommand
        {
            get;
            private set;
        }

        private KnowledgeItem _ki;
        private readonly KnowledgeItemAccessor _kiAccessor;

        #endregion

        #region methods

        private int Add()
        {
            return _kiAccessor.Add(_ki);
        }

        private bool Save()
        {
            return _kiAccessor.Update(_ki);
        }

        #endregion

        #region Implementation of IDataErrorInfo

        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <returns>
        /// The error message for the property. The default is an empty string ("").
        /// </returns>
        /// <param name="columnName">The name of the property whose error message to get. </param>
        public string this[string columnName]
        {
            get
            {
                var msg = "";
                switch (columnName)
                {
                    case ContentPropertyName:
                        if (string.IsNullOrEmpty(_ki.Content))
                            msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredContentMsg).ToString();
                        break;
                    case ClassLevelPropertyName:
                        if (_ki.ClassLevel <= 0)
                            msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredClassMsg).ToString();
                        break;
                    case SubjectPropertyName:
                        if (string.IsNullOrEmpty(_ki.Subject))
                            msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredSubjectMsg).ToString();
                        break;
                    case TopicPropertyName:
                        if (string.IsNullOrEmpty(_ki.Topic))
                            msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredTopicMsg).ToString();
                        break;
                    default:
                        break;
                }
                RaisePropertyChanged(CanSavePropertyName);
                return msg;
            }
        }

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        /// <returns>
        /// An error message indicating what is wrong with this object. The default is an empty string ("").
        /// </returns>
        public string Error
        {
            get
            {
                var msg = "";
                if (string.IsNullOrEmpty(Content))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredContentMsg).ToString();
                if (ClassLevel <= 0)
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredClassMsg).ToString();
                if (string.IsNullOrEmpty(Subject))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredSubjectMsg).ToString();
                if (string.IsNullOrEmpty(Topic))
                    msg = TranslationManager.Instance.Translate(DataHelper.KIRequiredTopicMsg).ToString();
                return msg;
            }
        }

        #endregion
    }
}